/* spitest.c
 * SPI test code; relays all spi messages to UART and vice versa
 * 
 * John Boiles
 * 10 November 2008
 */

#include <inttypes.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <uart.c>

//The clocksource determines the timer's frequency
//CS = 1 ClkIO = Clk
//CS = 2 ClkIO = Clk / 8
//CS = 3 ClkIO = Clk / 64
//CS = 4 ClkIO = Clk / 256
//CS = 5 ClkIO = Clk / 1024//CS = 6,7 External Clock
//# define TIMER0_CLOCKSOURCE _BV(CS02) //| _BV(CS00)
# define TIMER1_CLOCKSOURCE _BV(CS11) //Clock / 8

//Initialize SPI for slave use 
/*
In External Clock mode 0 (USICS0 = 0), DI is sampled at positive edges, and DO 
is changed (data register is shifted by one) at negative edges. External Clock 
mode 1 (USICS0 = 1) uses the opposite edges versus mode 0, i.e., samples data 
at negative and changes the output at positive edges. The USI clock modes 
corresponds to the SPI data mode 0 and 1.
*/
//USICS1 - select external clock
//USICS0 - 0:pos edge, 1:neg edge
//USIDR
//USISR - Flags and such
//USICR

void SPI_SlaveInit(void){
  //External clock, enable interrupts
  USICR = ((1<<USIWM0)|(1<<USICS1));//|(1<<USIOIE)|(1<<USISIE));
  //Clear interrupt flags
  USISR = (1<<USIOIF) | (1<<USISIF);
}

//Uses Polling
char SPI_SlaveTransfer(char tx){
  USIDR = tx;
  //Clear overflow interrupt flag
  USISR = (1<<USIOIF);
  //Wait for overflow interrupt flag to be set
  while(!(USISR & (1<<USIOIF)));
  return USIDR;
}

void SPI_SlaveTx(char tx){
  USIDR = tx;
}

//Overflow interrupt -- occurs after data is received
volatile char RX = '!';
ISR (USI_OVERFLOW_vect){
  RX = USIDR;
  UART_OutChar(RX);
  //Clear overflow interrupt flag
  USISR = (1<<USIOIF);
  
}
ISR (USI_START_vect){
  UART_OutChar('&');
  //Clear start condition interrupt flag
  USISR = (1<<USISIF);
} 

//Initial configuration
void
ioinit (void)              
{

  //Configure timer registers
  //TCCR0A = 0;
  TCCR1A = 0;
  //TCCR0B |= TIMER0_CLOCKSOURCE;
  //TCCR1B
  //Pin 7 - ICNC1 - 1 turns on noise canceling for IC
  //Pin 6 - ICES1 - 1 specifies rising edge ICdri
  TCCR1B |= TIMER1_CLOCKSOURCE | _BV(ICES1) | _BV(ICNC1);

  //IO Port direction registers for my H-Bridge Board rev1
  DDRB = 0x47;
  DDRD = 0x01;
  //Set Motor Direction:
  PORTB = 0x01;

  //USIDR = '1';

  //Enable Input Capture Interrupt
  //TIMSK |= _BV(ICIE1);
  sei ();
}

int
main (void)
{
  UART_Init(38400);
  ioinit ();
  UART_OutChar('#');


  /* loop forever, the interrupts are doing the rest */  
  while (1){
    UART_OutChar(SPI_SlaveTransfer('!'));
    
    //char in = UART_InChar();
    //UART_OutChar(in);
    //SPI_SlaveTx(in);                   
  }

  return (0);
}
